//
//  ModuleList.m
//
//  a simple storage class that holds all the information BackSpace needs
//  about each module.  This file contains 2 classes; one for the information
//  on a single module and one for a list to store those ModuleInfo's
//
//  You may freely copy, distribute, and reuse the code in this example.
//  NeXT disclaims any warranty of any kind, expressed or implied, as to its
//  fitness for any particular use.

#import "ModuleList.h"
#import <stdlib.h> // for free() etc
#import <strings.h>	 // for strcasecmp()
#import <objc/hashtable.h> // for NXCopyStringBuffer()

#define str_copy(str) ((str == NULL) ? NULL : NXCopyStringBuffer(str))
#define str_free(str) { if (str != NULL) free(str); }

@implementation ModuleInfo

- init { return [self initWithView:nil name:NULL path:NULL]; }

- initWithView:aView name:(const char *) aName path:(const char *) aPath
{
	[super init];

	view = aView;
	viewName = str_copy(aName);
	path = str_copy(aPath);

	return self;
}

- setView:newView
{
	id oldView = view;

	view = newView;

	return oldView;
}

- view { return view; }

- setHeader:(struct mach_header *) h { header = h; return self; }

- (struct mach_header *) header { return header; }

- (const char *) viewName { return viewName; }

- (const char *) path { return path; }

- setPath:(const char *) p
{
	str_free(path);
	path = str_copy(p);

	return self;
}

- appendPath:(const char *) p
{
	if (altPaths != NULL) {
		altPaths = realloc(altPaths, strlen(altPaths) + strlen(p) + 2);
		(void) strcat(strcat(altPaths,"\t"), p);
		}
	else altPaths = str_copy(p);

	return self;
}

// if the path is bogus, this will set the path to the next one
// returns self if successful, nil if there is no additional path

- useNextPath
{
	char *p1 = altPaths, *p2 = altPaths;

	if (altPaths == NULL) return nil;

	while (*p1 != '\0' && *p1 != '\t') p1++;

	if (*p1 == '\t') {
		*p1 = '\0';
		path = realloc(path, strlen(p1) + 1);
		(void) strcpy(path, p1);
		while (*p2++ = *p1++);
		altPaths = realloc(altPaths, strlen(altPaths) + 1);
		}
	else { // last one
		str_free(path);
		path = altPaths;
		altPaths = NULL;
		}

	return self;
}

- discardAltPaths
{
	str_free(altPaths);
	altPaths = NULL;

	return self;
}

- free
{
	[view free];
	str_free(viewName);
	str_free(path);
	str_free(altPaths);

	return [super free];
}

@end

@implementation ModuleList

- (const char *) nameAt:(int) i
{
	return [[self objectAt:i] viewName];
}

- (int) indexOfName:(const char *) name;
{
	int i, n = [self count];

	for (i = 0; i < n; i++) {
		if (strcmp(name, [[self objectAt:i] viewName]) == 0) return i;
		}

	return -1;
}

- viewAt:(int) i
{
	return [[self objectAt:i] view];
}

static int docompare(const void *x, const void *y)
{
	return strcasecmp([(id) (*(ModuleInfo **) x) viewName], [(id) (*(ModuleInfo **) y) viewName]);
}

- sort
{
	qsort((ModuleInfo **) dataPtr, numElements, sizeof(id), docompare);

	return self;
}

@end
